﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DMPlugin
{
    class DM
    {
        private Dm.dmsoft pluginInstance;
        private string pluginPath;

        public DM()
        {
            this.pluginPath = Application.StartupPath + "/plugin/dm.dll";
            initPlugin();
        }

        public DM(string pluginPath)
        {
            this.pluginPath = pluginPath;
            initPlugin();
        }

        private void initPlugin()
        {
            string command = $"regsvr32 -s {this.pluginPath}";
            Process myProcess = new Process();
            ProcessStartInfo myProcessStartInfo = new ProcessStartInfo("cmd.exe");
            myProcessStartInfo.UseShellExecute = false;
            myProcessStartInfo.CreateNoWindow = true;
            myProcessStartInfo.RedirectStandardOutput = true;
            myProcess.StartInfo = myProcessStartInfo;
            myProcessStartInfo.Arguments = "/c " + command;
            myProcess.Start();
            StreamReader myStreamReader = myProcess.StandardOutput;
            myProcess.Close();

            // init dm instance
            pluginInstance = new Dm.dmsoft();
        }

        public Dm.dmsoft Instance() => pluginInstance;

        public string GetBasePath() => pluginInstance.GetBasePath();

        /// <summary>
        /// [收费]
        /// 返回当前进程已经创建的dm对象个数.
        /// </summary>
        /// <returns></returns>
        public int GetDmCount() => pluginInstance.GetDmCount();

        /// <summary>
        /// 返回当前大漠对象的ID值，这个值对于每个对象是唯一存在的。
        /// 可以用来判定两个大漠对象是否一致.
        /// </summary>
        /// <returns></returns>
        public int GetID() => pluginInstance.GetID();

        /// <summary>
        /// 获取插件命令的最后错误
        /// </summary>
        /// <returns></returns>
        public int GetLastError() => pluginInstance.GetLastError();

        /// <summary>
        /// 获取全局路径.(可用于调试)
        /// </summary>
        /// <returns></returns>
        public string GetPath() => pluginInstance.GetPath();

        public int Reg(string regCode, string verInfo) => pluginInstance.Reg(regCode, verInfo);
        public int RegNoMac(string regCode, string verInfo) => pluginInstance.RegNoMac(regCode, verInfo);
        public int RegEx(string regCode, string verInfo, string ip) => pluginInstance.RegEx(regCode, verInfo, ip);
        public int RegExNoMac(string regCode, string verInfo, string ip) => pluginInstance.RegExNoMac(regCode, verInfo, ip);

        /// <summary>
        /// 设定图色的获取方式，默认是显示器或者后台窗口(具体参考BindWindow)
        /// </summary>
        /// <param name="mode">
        /// 图色输入模式取值有以下几种
        /// "screen" 这个是默认的模式，表示使用显示器或者后台窗口
        /// "pic:file" 指定输入模式为指定的图片,如果使用了这个模式，则所有和图色相关的函数
        /// 均视为对此图片进行处理，比如文字识别查找图片 颜色 等等一切图色函数.
        /// 需要注意的是，设定以后，此图片就已经加入了缓冲，如果更改了源图片内容，那么需要释放此缓冲，重新设置.
        /// </param>
        /// <returns></returns>
        public bool SetDisplayInput(string mode) => pluginInstance.SetDisplayInput(mode).Success();

        public bool SetPath(string path) => pluginInstance.SetPath(path).Success();

        public string Ver() => pluginInstance.Ver();

        /// <summary>
        /// 设置是否弹出错误信息,默认是打开.
        /// </summary>
        /// <returns></returns>
        public bool EnableShowErrorMsg() => pluginInstance.SetShowErrorMsg(1).Success();
        public bool DisableShowErrorMsg() => pluginInstance.SetShowErrorMsg(0).Success();

        /// <summary>
        /// [收费]
        /// 设置EnumWindow  EnumWindowByProcess  EnumWindowSuper的最长延时. 内部默认超时是5秒.
        /// 注: 有些时候，窗口过多，并且窗口结构过于复杂，可能枚举的时间过长. 
        /// 那么需要调用这个函数来延长时间。避免漏掉窗口.
        /// </summary>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public bool SetEnumWindowDelay(int timeout) => pluginInstance.SetEnumWindowDelay(timeout).Success();

        public Asm Asm() => new Asm(this);
        public Asm Asm(int hwnd) => new Asm(this, hwnd);
        public Background Background(int hwnd) => new Background(this, hwnd);
        public ColorPic ColorPic() => new ColorPic(this);
        public Dict Dict() => new Dict(this);
        public Guard Guard() => new Guard(this);
        public Input Input() => new Input(this);
        public Others Others() => new Others(this);
        public System System() => new System(this);
        public Text Text() => new Text(this);
        public Window Window() => new Window(this);
        public Window Window(int hwnd) => new Window(this, hwnd);
    }

    class DmClassModule
    {
        private DM _dm;

        public Dm.dmsoft instance()
        {
            return _dm.Instance();
        }

        public DmClassModule(DM dmInstance)
        {
            _dm = dmInstance;
        }
    }

    // dm windows
    class Window : DmClassModule
    {
        private int hwnd = 0;
        public Window(DM dmInstance, int hwnd = 0) : base(dmInstance)
        {
            this.hwnd = hwnd;
        }

        /// <summary>
        /// 检测指定窗口所在线程输入法是否开启
        /// </summary>
        /// <param name="inputMethod">
        /// 输入法名字。具体输入法名字对应表查看注册表中以下位置:
        /// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts
        /// 下面的每一项下的Layout Text的值就是输入法名字
        /// </param>
        /// <returns></returns>
        public bool CheckInputMethod(string inputMethod) => instance().CheckInputMethod(hwnd, inputMethod).Success();
        public bool ActiveInputMethod(string inputMethod) => instance().ActiveInputMethod(hwnd, inputMethod).Success();
        /// <summary>
        ///   把窗口坐标转换为屏幕坐标 
        /// </summary>
        /// <param name="hwnd">int</param>
        /// <param name="point">Point</param>
        /// <returns>Point </returns>
        public Point ClientToScreen(Point point)
        {
            object x = point.X;
            object y = point.Y;

            instance().ClientToScreen(hwnd, ref x, ref y);

            point.X = Convert.ToInt32(x);
            point.Y = Convert.ToInt32(y);

            return point;
        }
        /// <summary>
        ///    根据指定条件,枚举系统中符合条件的窗口,可以枚举到按键自带的无法枚举到的窗口
        /// </summary>
        /// <param name="parentHwnd">获得的窗口句柄是该窗口的子窗口的窗口句柄,取0时为获得桌面句柄</param>
        /// <param name="title">窗口标题. 此参数是模糊匹配</param>
        /// <param name="className">窗口类名. 此参数是模糊匹配</param>
        /// <param name="filter">
        /// 1  : 匹配窗口标题,参数title有效 
        /// 2  : 匹配窗口类名,参数class_name有效.
        /// 4  : 只匹配指定父窗口的第一层孩子窗口
        /// 8  : 匹配所有者窗口为0的窗口,即顶级窗口
        /// 16 : 匹配可见的窗口
        /// 32 : 匹配出的窗口按照窗口打开顺序依次排列 <收费功能>
        /// 这些值可以相加,比如4+8+16就是类似于任务管理器中的窗口列表
        /// </param>
        /// <returns></returns>
        public List<int> EnumWindow(int parentHwnd, string title, string className = "", int filter = 1)
        {
            string retData = instance().EnumWindow(parentHwnd, title, className, filter);
            return Tools.StringToListInt(',', retData);
        }


        public List<int> EnumWindowByProcess(string processName, string title, string className = "", int filter = 1)
        {
            string retData = instance().EnumWindowByProcess(processName, title, className, filter);
            return Tools.StringToListInt(',', retData);
        }

        /// <summary>
        /// 查找符合类名或者标题名的顶层可见窗口
        /// </summary>
        /// <param name="className">窗口类名，如果为空，则匹配所有. 这里的匹配是模糊匹配</param>
        /// <param name="title">窗口标题,如果为空，则匹配所有.这里的匹配是模糊匹配</param>
        /// <returns>整形数表示的窗口句柄，没找到返回0</returns>
        public int FindWindow(string className = "", string title = "")
        {
            return instance().FindWindow(className, title);
        }

        /// <summary>
        /// 查找符合类名或者标题名的顶层可见窗口,如果指定了parent,则在parent的第一层子窗口中查找.
        /// </summary>
        /// <param name="parentHwnd"> 父窗口句柄，如果为空，则匹配所有顶层窗口</param>
        /// <param name="className">窗口类名，如果为空，则匹配所有. 这里的匹配是模糊匹配</param>
        /// <param name="title">窗口标题,如果为空，则匹配所有. 这里的匹配是模糊匹配</param>
        /// <returns>整形数表示的窗口句柄，没找到返回0</returns>
        public int FindWindowEx(int parentHwnd = 0, string className = "", string title = "")
        {
            return instance().FindWindowEx(parentHwnd, className, title);
        }

        /// <summary>
        /// 根据指定的进程名字，来查找可见窗口.  <收费功能>
        /// </summary>
        /// <param name="processName">进程名. 比如(notepad.exe).这里是精确匹配,但不区分大小写</param>
        /// <param name="className">窗口类名，如果为空，则匹配所有. 这里的匹配是模糊匹配</param>
        /// <param name="title">窗口标题,如果为空，则匹配所有.这里的匹配是模糊匹配</param>
        /// <returns>整形数表示的窗口句柄，没找到返回0</returns>
        public int FindWindowByProcess(string processName, string className = "", string title = "")
        {
            return instance().FindWindowByProcess(processName, className, title);
        }


        /// <summary>
        /// 根据指定的进程Id，来查找可见窗口.  <收费功能>
        /// </summary>
        /// <param name="processId">进程id</param>
        /// <param name="className"> 窗口类名，如果为空，则匹配所有. 这里的匹配是模糊匹配</param>
        /// <param name="title">窗口标题,如果为空，则匹配所有.这里的匹配是模糊匹配</param>
        /// <returns>整形数表示的窗口句柄，没找到返回0</returns>
        public int FindWindowByProcessId(int processId, string className = "", string title = "")
        {
            return instance().FindWindowByProcessId(processId, className, title);
        }

        /// <summary>
        /// 根据两组设定条件来查找指定窗口. <收费功能，具体详情点击查看>
        /// </summary>
        /// <param name="condition1"></param>
        /// <param name="condition2"></param>
        /// <returns>整形数表示的窗口句柄，没找到返回0</returns>
        public int FindWindowSuper(FindWindowSuperCondition condition1, FindWindowSuperCondition condition2)
        {
            return instance().FindWindowSuper(
                condition1.Target,
                condition1.Flag,
                condition1.Type,
                condition2.Target,
                condition2.Flag,
                condition2.Type
                );
        }

        /// <summary>
        /// 获取窗口客户区域在屏幕上的位置
        /// </summary>
        /// <returns></returns>
        public Rect GetClientRect()
        {
            object left, top, right, bottom;
            int ret = instance().GetClientRect(hwnd, out left, out top, out right, out bottom);
            if (ret == 0)
            {
                return new Rect();
            }

            return new Rect
            {
                Left = Convert.ToInt32(left),
                Top = Convert.ToInt32(top),
                Right = Convert.ToInt32(right),
                Bottom = Convert.ToInt32(bottom)
            };
        }

        /// <summary>
        /// 获取窗口客户区域的宽度和高度
        /// </summary>
        /// <returns></returns>
        public Size GetClientSize()
        {
            object width, height;
            int ret = instance().GetClientSize(hwnd, out width, out height);
            if (ret == 0)
            {
                return new Size();
            }

            return new Size
            {
                Width = Convert.ToInt32(width),
                Height = Convert.ToInt32(height)
            };
        }

        /// <summary>
        /// 获取顶层活动窗口中具有输入焦点的窗口句柄 
        /// </summary>
        /// <returns>返回整型表示的窗口句柄</returns>
        public int GetForegroundFocus()
        {
            return instance().GetForegroundFocus();
        }

        /// <summary>
        /// 获取顶层活动窗口,可以获取到按键自带插件无法获取到的句柄
        /// </summary>
        /// <returns>返回整型表示的窗口句柄</returns>
        public int GetForegroundWindow()
        {
            return instance().GetForegroundWindow();
        }

        /// <summary>
        /// 获取鼠标指向的窗口句柄,可以获取到按键自带的插件无法获取到的句柄
        /// </summary>
        /// <returns>返回整型表示的窗口句柄</returns>
        public int GetMousePointWindow()
        {
            return instance().GetMousePointWindow();
        }

        /// <summary>
        /// 获取给定坐标的窗口句柄,可以获取到按键自带的插件无法获取到的句柄
        /// </summary>
        /// <param name="point"></param>
        /// <returns>返回整型表示的窗口句柄</returns>
        public int GetPointWindow(Point point)
        {
            return instance().GetPointWindow(point.X, point.Y);
        }

        /// <summary>
        /// 获取特殊窗口
        /// </summary>
        /// <param name="flag">
        /// Flag 整形数: 取值定义如下
        ///     0: 获取桌面窗口
        ///     1: 获取任务栏窗口
        /// </param>
        /// <returns>以整型数表示的窗口句柄</returns>
        public int GetSpecialWindow(int flag)
        {
            return instance().GetSpecialWindow(flag);
        }

        /// <summary>
        /// 获取给定窗口相关的窗口句柄
        /// </summary>
        /// <param name="flag">
        /// 0 : 获取父窗口
        /// 1 : 获取第一个儿子窗口
        /// 2 : 获取First 窗口
        /// 3 : 获取Last窗口
        /// 4 : 获取下一个窗口
        /// 5 : 获取上一个窗口
        /// 6 : 获取拥有者窗口
        /// 7 : 获取顶层窗口
        /// </param>
        /// <returns>返回整型表示的窗口句柄</returns>
        public int GetWindow(int flag)
        {
            return instance().GetWindow(hwnd, flag);
        }

        /// <summary>
        /// 获取窗口的类名
        /// </summary>
        /// <returns></returns>
        public string GetWindowClass()
        {
            return instance().GetWindowClass(hwnd);
        }

        /// <summary>
        /// 获取指定窗口所在的进程ID
        /// </summary>
        /// <returns></returns>
        public int GetWindowProcessId()
        {
            return instance().GetWindowProcessId(hwnd);
        }

        /// <summary>
        /// 获取指定窗口所在的进程的exe文件全路径
        /// </summary>
        /// <returns></returns>
        public string GetWindowProcessPath()
        {
            return instance().GetWindowProcessPath(hwnd);
        }

        /// <summary>
        /// 获取窗口在屏幕上的位置
        /// </summary>
        /// <returns></returns>
        public Rect GetWindowRect()
        {
            object left, top, right, bottom;
            int ret = instance().GetWindowRect(hwnd, out left, out top, out right, out bottom);
            if (ret == 0)
            {
                return new Rect();
            }

            return new Rect
            {
                Left = Convert.ToInt32(left),
                Top = Convert.ToInt32(top),
                Right = Convert.ToInt32(right),
                Bottom = Convert.ToInt32(bottom)
            };
        }

        /// <summary>
        /// 获取指定窗口的一些属性
        /// </summary>
        /// <param name="flag">
        /// 0 : 判断窗口是否存在
        /// 1 : 判断窗口是否处于激活
        /// 2 : 判断窗口是否可见
        /// 3 : 判断窗口是否最小化
        /// 4 : 判断窗口是否最大化
        /// 5 : 判断窗口是否置顶
        /// 6 : 判断窗口是否无响应
        /// </param>
        /// <returns></returns>
        public bool GetWindowState(int flag)
        {
            return instance().GetWindowState(hwnd, flag).Success();
        }

        /// <summary>
        /// 获取窗口的标题
        /// </summary>
        /// <returns></returns>
        public string GetWindowTitle()
        {
            return instance().GetWindowTitle(hwnd);
        }

        /// <summary>
        /// 移动指定窗口到指定位置
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public bool MoveTo(Point point)
        {
            return instance().MoveWindow(hwnd, point.X, point.Y).Success();
        }

        /// <summary>
        /// 把屏幕坐标转换为窗口坐标
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public Point ScreenToClient(Point point)
        {
            object x = point.X;
            object y = point.Y;

            if (instance().ScreenToClient(hwnd, ref x, ref y).Success())
            {
                return new Point
                {
                    X = Convert.ToInt32(x),
                    Y = Convert.ToInt32(y)
                };
            }
            return point;
        }

        /// <summary>
        /// 向指定窗口发送粘贴命令. 把剪贴板的内容发送到目标窗口.
        /// </summary>
        /// <returns></returns>
        public bool SendPaste()
        {
            return instance().SendPaste(hwnd).Success();
        }

        /// <summary>
        /// 向指定窗口发送文本数据
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public bool SendString(string str, bool old = false)
        {
            if (old)
            {
                return instance().SendString2(hwnd, str).Success();
            }
            return instance().SendString(hwnd, str).Success();
        }

        /// <summary>
        /// 向绑定的窗口发送文本数据.必须配合dx.public.input.ime属性.  <收费功能>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public bool SendStringIme(string str)
        {
            return instance().SendStringIme(str).Success();
        }


        /// <summary>
        /// 设置窗口客户区域的宽度和高度
        /// </summary>
        /// <param name="size"></param>
        /// <returns></returns>
        public bool SetClientSize(Size size)
        {
            return instance().SetClientSize(hwnd, size.Width, size.Height).Success();
        }

        /// <summary>
        /// 设置窗口的大小
        /// </summary>
        /// <param name="size"></param>
        /// <returns></returns>
        public bool SetWindowSize(Size size)
        {
            return instance().SetWindowSize(hwnd, size.Width, size.Height).Success();
        }

        /// <summary>
        /// 设置窗口的状态
        /// </summary>
        /// <param name="flag"></param>
        /// <returns></returns>
        public bool SetWindowState(int flag)
        {
            return instance().SetWindowState(hwnd, flag).Success();
        }

        /// <summary>
        /// 设置窗口的标题
        /// </summary>
        /// <param name="title"></param>
        /// <returns></returns>
        public bool SetWindowTitle(string title)
        {
            return instance().SetWindowText(hwnd, title).Success();
        }

        /// <summary>
        /// 设置窗口的透明度
        /// </summary>
        /// <param name="trans">透明度取值(0-255) 越小透明度越大 0为完全透明(不可见) 255为完全显示(不透明)</param>
        /// <returns></returns>
        public bool SetWindowTransparent(int trans)
        {
            return instance().SetWindowTransparent(hwnd, trans).Success();
        }
    }

    class Guard : DmClassModule
    {
        public Guard(DM dmInstance) : base(dmInstance) { }
        public bool Enable(string mode)
        {
            return instance().DmGuard(1, mode).Success();
        }

        public bool Disable()
        {
            return instance().DmGuard(0, "").Success();
        }
    }

    class Background : DmClassModule
    {
        private int hwnd;
        public Background(DM dmInstance, int hwnd) : base(dmInstance) { this.hwnd = hwnd; }

        /// <summary>
        /// 绑定指定的窗口,并指定这个窗口的屏幕颜色获取方式,鼠标仿真模式,键盘仿真模式,以及模式设定, 
        /// [高级用户可以参考BindWindowEx更加灵活强大]
        /// </summary>
        /// <param name="display"></param>
        /// <param name="mouse"></param>
        /// <param name="keyboard"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public bool BindWindow(string display, string mouse, string keyboard, int mode)
        {
            return instance().BindWindow(hwnd, display, mouse, keyboard, mode).Success();
        }

        /// <summary>
        /// 绑定指定的窗口,并指定这个窗口的屏幕颜色获取方式,鼠标仿真模式,键盘仿真模式 
        /// [高级用户使用]
        /// </summary>
        /// <param name="display"></param>
        /// <param name="mouse"></param>
        /// <param name="keyboard"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public bool BindWindowEx(string display, string mouse, string keyboard, string publicDesc, int mode)
        {
            return instance().BindWindowEx(hwnd, display, mouse, keyboard, publicDesc, mode).Success();
        }

        /// <summary>
        /// 降低目标窗口所在进程的CPU占用
        /// 注意: 此接口必须在绑定窗口成功以后调用，
        /// 而且必须保证目标窗口可以
        /// 支持dx.graphic.3d 
        /// 或者dx.graphic.3d.8
        /// 或者dx.graphic.2d
        /// 或者dx.graphic.2d.2
        /// 方式截图，否则降低CPU无效.
        /// 因为降低CPU是通过降低窗口刷新速度来实现，
        /// 所以注意，开启此功能以后会导致窗口刷新速度变慢.
        /// </summary>
        /// <param name="rate"></param>
        /// <returns></returns>
        public bool DownCPU(int rate) => instance().DownCpu(rate).Success();

        /// <summary>
        /// 设置是否暂时关闭或者开启后台功能. 默认是开启.    
        /// [收费功能]
        /// 注: 注意切换到前台以后,
        /// 相当于dm_ret = dm.BindWindow(hwnd,"normal","normal","normal",0)
        /// 图色键鼠全部是前台.
        /// 如果你经常有频繁切换后台和前台的操作，推荐使用这个函数.
        /// 同时要注意,如果有多个对象绑定了同个窗口，其中任何一个对象禁止了后台,
        /// 那么其他对象后台也同样失效.
        /// </summary>
        /// <returns></returns>
        public bool BindEnable() => instance().EnableBind(1).Success();

        public bool BindDisable() => instance().EnableBind(0).Success();

        /// <summary>
        /// 设置是否开启后台假激活功能. 默认是关闭. 一般用不到. 除非有人有特殊需求. 注意看注释.     
        /// [收费功能]
        /// 注: 此接口的含义并不是关闭或者开启窗口假激活功能(dx.public.active.api或者dx.public.active.message). 而是说有些时候，本来窗口没有激活并且在没有绑定的状态下，可以正常使用的功能，而在窗口绑定以后,并且窗口在非激活状态下,此时由于绑定的锁定导致无法使用. 那么，你就需要把你的部分代码用EnableFakeActive来保护起来。这样就让我的插件认为你的这段代码是在窗口激活状态下执行.
        /// 另外，此函数开启以后，有可能会让前台影响到后台.所以如果不是特殊情况，最好是关闭.
        /// 有些时候，有人会故意利用这个前台影响后台的作用，做类似同步器的软件，那这个函数就很有作用了
        /// </summary>
        /// <returns></returns>
        public bool FakeActiveEnable() => instance().EnableFakeActive(1).Success();
        public bool FakeActiveDisable() => instance().EnableFakeActive(0).Success();


        /// <summary>
        /// 设置是否关闭绑定窗口所在进程的输入法.
        /// 注: 此函数必须在绑定后调用才有效果.
        /// </summary>
        /// <returns></returns>
        public bool ImeEnable() => instance().EnableIme(1).Success();
        public bool ImeDisable() => instance().EnableIme(0).Success();


        /// <summary>
        /// 是否在使用dx键盘时开启windows消息.默认开启
        /// [收费功能]
        /// 注: 此接口必须在绑定之后才能调用。特殊时候使用.
        /// </summary>
        /// <returns></returns>
        public bool KeypadMsgEnable() => instance().EnableKeypadMsg(1).Success();
        public bool KeypadMsgDisable() => instance().EnableKeypadMsg(0).Success();

        /// <summary>
        /// 键盘消息发送补丁. 默认是关闭
        /// 注: 此接口必须在绑定之后才能调用
        /// </summary>
        /// <returns></returns>
        public bool KeypadPatchEnable() => instance().EnableKeypadPatch(1).Success();
        public bool KeypadPatchDisable() => instance().EnableKeypadPatch(0).Success();

        /// <summary>
        /// [收费] 
        /// 键盘消息采用同步发送模式.默认异步.
        /// 注: 此接口必须在绑定之后才能调用。
        /// 有些时候，如果是异步发送，如果发送动作太快,中间没有延时,有可能下个动作会影响前面的.
        /// 而用同步就没有这个担心.
        /// </summary>
        /// <returns></returns>
        public bool KeypadSyncEnable(int timeout) => instance().EnableKeypadSync(1, timeout).Success();
        public bool KeypadSyncDisable() => instance().EnableKeypadSync(0, 0).Success();

        /// <summary>
        /// [收费]
        /// 是否在使用dx鼠标时开启windows消息.默认开启
        /// 注: 此接口必须在绑定之后才能调用。特殊时候使用.
        /// </summary>
        /// <returns></returns>
        public bool MouseMsgEnable() => instance().EnableMouseMsg(1).Success();
        public bool MouseMsgDisable() => instance().EnableMouseMsg(0).Success();

        /// <summary>
        /// [收费] 
        /// 鼠标消息采用同步发送模式.默认异步.
        /// 注: 此接口必须在绑定之后才能调用。
        /// 有些时候，如果是异步发送，如果发送动作太快,中间没有延时,有可能下个动作会影响前面的.
        /// 而用同步就没有这个担心.
        /// </summary>
        /// <returns></returns>
        public bool MouseSyncEnable(int timeout) => instance().EnableMouseSync(1, timeout).Success();
        public bool MouseSyncDisable() => instance().EnableMouseSync(0, 0).Success();


        /// <summary>
        /// [收费]
        /// 键盘动作模拟真实操作,点击延时随机.
        /// 注: 此接口对KeyPress KeyPressChar KeyPressStr起作用。具体表现是键盘按下和弹起的间隔会在
        /// 当前设定延时的基础上,上下随机浮动50%. 假如设定的键盘延时是100,那么这个延时可能就是50-150之间的一个值.
        /// 设定延时的函数是 SetKeypadDelay
        /// </summary>
        /// <returns></returns>
        public bool RealKeypadEnable() => instance().EnableRealKeypad(1).Success();
        public bool RealKeypadDisable() => instance().EnableRealKeypad(0).Success();

        /// <summary>
        /// [收费]
        /// 鼠标动作模拟真实操作,带移动轨迹,以及点击延时随机
        /// 注: 此接口同样对LeftClick RightClick MiddleClick LeftDoubleClick起作用。具体表现是鼠标按下和弹起的间隔会在
        /// 当前设定延时的基础上,上下随机浮动50%. 假如设定的鼠标延时是100,那么这个延时可能就是50-150之间的一个值.
        /// 设定延时的函数是 SetMouseDelay
        /// </summary>
        /// <returns></returns>
        public bool RealMouseEnable(int delay, int step) => instance().EnableRealMouse(1, delay, step).Success();
        public bool RealMouseDisable() => instance().EnableRealMouse(0, 0, 0).Success();

        /// <summary>
        /// 设置是否开启高速dx键鼠模式。 默认是关闭.
        /// 注: 此函数开启的后果就是，所有dx键鼠操作将不会等待，适用于某些特殊的场合(比如避免窗口无响应导致宿主进程也卡死的问题).
        /// EnableMouseSync和EnableKeyboardSync开启以后，此函数就无效了.
        /// 此函数可能在部分窗口下会有副作用，谨慎使用!!
        /// </summary>
        /// <returns></returns>
        public bool SpeedDxEnable() => instance().EnableSpeedDx(1).Success();
        public bool SpeedDxDisable() => instance().EnableSpeedDx(0).Success();

        /// <summary>
        /// [收费]
        /// 强制解除绑定窗口,并释放系统资源
        /// 注: 此接口一般用在BindWindow和BindWindowEx中，使用了模式1 3 5 7或者属性dx.public.hide.dll后，在线程或者进程结束后，没有正确调用UnBindWindow而导致下次绑定无法成功时，可以先调用这个函数强制解除绑定，并释放资源，再进行绑定.
        /// 此接口不可替代UnBindWindow.只是用在非常时刻.切记.
        /// 一般情况下可以无条件的在BindWindow或者BindWindowEx之前调用一次此函数。保证此刻窗口处于非绑定状态.
        /// 另外，需要注意的是,此函数只可以强制解绑在同进程绑定的窗口.不可在不同的进程解绑别的进程绑定的窗口.(会产生异常)
        /// </summary>
        /// <returns></returns>
        public bool ForceUnBindWindow() => instance().ForceUnBindWindow(hwnd).Success();

        /// <summary>
        /// [收费]
        /// 判定指定窗口是否已经被后台绑定. (前台无法判定)
        /// </summary>
        /// <returns></returns>
        public bool IsBind() => instance().IsBind(hwnd).Success();

        /// <summary>
        /// [收费]
        /// 锁定指定窗口的图色数据(不刷新).  
        /// 注意: 此接口只对图色为dx.graphic.3d  dx.graphic.3d.8 dx.graphic.2d  dx.graphic.2d.2有效
        /// </summary>
        /// <returns></returns>
        public bool LockDisplayEnable() => instance().LockDisplay(1).Success();
        public bool LockDisplayDisable() => instance().LockDisplay(0).Success();

        /// <summary>
        /// 禁止外部输入到指定窗
        /// 注意:此接口只针对dx键鼠. 普通键鼠无效. 
        /// 有时候，绑定为dx2 鼠标模式时(或者没有锁定鼠标位置或状态时)，在脚本处理过程中，在某个时候需要临时锁定外部输入，以免外部干扰，那么这个函数就非常有用.
        /// 比如某个信息，需要鼠标移动到某个位置才可以获取，但这时，如果外部干扰，那么很可能就会获取失败，所以，这时候就很有必要锁定外部输入.
        /// 当然，锁定完以后，记得要解除锁定，否则外部永远都无法输入了，除非解除了窗口绑定.
        /// </summary>
        /// <returns></returns>
        public bool LockInputDisable() => instance().LockInput(0).Success();
        public bool LockInputBoth() => instance().LockInput(1).Success();
        public bool LockInputMouse() => instance().LockInput(2).Success();
        public bool LockInputKeypad() => instance().LockInput(3).Success();

        /// <summary>
        /// 设置前台鼠标在屏幕上的活动范围.
        /// 注: 调用此函数后，一旦有窗口切换或者窗口移动的动作，那么限制立刻失效.
        /// 如果想一直限制鼠标范围在指定的窗口客户区域，那么你需要启动一个线程，
        /// 并且时刻监视当前活动窗口，然后根据情况调用此函数限制鼠标范围.
        /// </summary>
        /// <param name="rect"></param>
        /// <returns></returns>
        public bool LockMouseRect(Rect rect) => instance().LockMouseRect(rect.Left, rect.Top, rect.Right, rect.Bottom).Success();
        public bool DisableLockMouseRect() => instance().LockMouseRect(0, 0, 0, 0).Success();


        /// <summary>
        /// 设置dx截图最长等待时间。内部默认是3000毫秒. 一般用不到调整这个.
        /// 注: 此接口仅对图色为dx.graphic.3d   dx.graphic.3d.8  dx.graphic.2d   dx.graphic.2d.2有效.其他图色模式无效.
        /// 默认情况下，截图需要等待一个延时，超时就认为截图失败.这个接口可以调整这个延时.某些时候或许有用.比如当窗口图色卡死(这时获取图色一定都是超时)，并且要判断窗口卡死，那么这个设置就很有用了。
        /// </summary>
        /// <param name="timeout">等待时间，单位是毫秒。 注意这里不能设置的过小，否则可能会导致截图失败,从而导致图色函数和文字识别失败.</param>
        /// <returns></returns>
        public bool SetDisplayDelay(int timeout) => instance().SetDisplayDelay(timeout).Success();

        /// <summary>
        /// [收费]
        /// 设置前台键鼠的模拟方式
        ///
        /// 注: 超级模拟和硬件模拟方式目前仅支持32位平台(目前测试正常的系统有xp,2003, vista, win7,2008). 64位平台暂时不支持.
        /// 超级模拟方式需要加载驱动，所以调用进程必须有管理员权限,参考如何关闭UAC.
        /// 加载驱动时，必须让安全软件放行.否则模拟无效.
        /// </summary>
        /// <param name="mode">
        /// 0 正常模式(默认模式)
        /// 1 超级模拟
        /// 2 硬件模拟
        /// </param>
        /// <returns>
        /// 0  : 插件没注册
        /// 1  : 成功
        /// -1 : 64位平台不支持
        /// -2 : 驱动释放失败.
        /// -3 : 驱动加载失败.可能是权限不够.参考UAC权限设置.
        /// </returns>
        public bool SetSimMode(int mode) => instance().SetSimMode(mode).Success();

        /// <summary>
        /// 解除绑定窗口,并释放系统资源.
        /// </summary>
        /// <returns></returns>
        public bool UnBindWindow() => instance().UnBindWindow().Success();

        ~Background()
        {
            UnBindWindow();
        }
    }

    class Asm : DmClassModule
    {
        private int hwnd;
        public Asm(DM dmInstance, int hwnd = 0) : base(dmInstance) { this.hwnd = hwnd; }

        public bool Add(string command) => instance().AsmAdd(command).Success();
        /// <summary>
        /// 
        /// </summary>
        /// <param name="mode">
        ///  0 : 在本进程中进行执行，这时hwnd无效
        ///  1 : 对hwnd指定的进程内执行,注入模式为创建远程线程
        /// </param>
        /// <returns></returns>
        public bool Call(int mode) => instance().AsmCall(hwnd, mode).Success();

        public bool Clear() => instance().AsmClear().Success();

        /// <summary>
        /// 把汇编缓冲区的指令转换为机器码 并用16进制字符串的形式输出
        /// </summary>
        /// <returns></returns>
        public string Code(int addr) => instance().AsmCode(addr);

        /// <summary>
        /// 把指定的机器码转换为汇编语言输出
        /// </summary>
        /// <param name="addr"></param>
        /// <returns></returns>
        public string Assemble(string code, int addr, bool IsUpperCase) => instance().Assemble(code, addr, IsUpperCase ? 1 : 0);
    }

    class Input : DmClassModule
    {
        public Input(DM dm) : base(dm) { }

        public Point GetCursorPos()
        {
            object x, y;
            if (instance().GetCursorPos(out x, out y).Success())
            {
                return new Point
                {
                    X = Convert.ToInt32(x),
                    Y = Convert.ToInt32(y),
                };
            }
            return new Point();
        }

        /// <summary>
        /// [后台特征码是收费功能]
        /// 获取鼠标特征码. 当BindWindow或者BindWindowEx中的mouse参数含有dx.mouse.cursor时，
        /// 获取到的是后台鼠标特征，否则是前台鼠标特征.
        /// 注: 当type为0时，和GetCursorShape等效.
        /// 另要特别注意,WIN7以及以上系统，必须在字体显示设置里把文字大小调整为默认(100%),否则特征码会变.如图所示.
        /// </summary>
        /// <returns></returns>
        public string GetCursorShape(int mode = 0) => instance().GetCursorShapeEx(mode);

        /// <summary>
        /// 获取鼠标热点位置.(参考工具中抓取鼠标后，那个闪动的点就是热点坐标,不是鼠标坐标)
        /// 当BindWindow或者BindWindowEx中的mouse参数含有dx.mouse.cursor时，
        /// 获取到的是后台鼠标热点位置，否则是前台鼠标热点位置.后台热点位置是收费功能
        /// </summary>
        /// <returns></returns>
        public Point GetCursorSpot() => instance().GetCursorSpot().ToPoint();


        /// <summary>
        /// GetKeyState alias
        /// 获取指定的按键状态.(前台信息, 不是后台)
        /// </summary>
        /// <param name="vkCode"></param>
        /// <returns></returns>
        public bool IsKeyPressing(int vkCode)
        {
            return instance().GetKeyState(vkCode) == 0;
        }

        public bool KeyDown(int vkCode) => instance().KeyDown(vkCode).Success();
        public bool KeyDownChar(string keyChar) => instance().KeyDownChar(keyChar).Success();
        public bool KeyUp(int vkCode) => instance().KeyUp(vkCode).Success();
        public bool KeyUpChar(string keyChar) => instance().KeyUpChar(keyChar).Success();
        public bool KeyPress(int vkCode) => instance().KeyPress(vkCode).Success();
        public bool KeyPressChar(string keyChar) => instance().KeyPressChar(keyChar).Success();
        /// <summary>
        /// 根据指定的字符串序列，依次按顺序按下其中的字符
        /// 注: 在某些情况下，SendString和SendString2都无法输入文字时，可以考虑用这个来输入.
        /// 但这个接口只支持"a-z 0-9 ~-=[]\;',./"和空格,其它字符一律不支持.(包括中国)
        /// </summary>
        /// <param name="str">需要按下的字符串序列. 比如"1234","abcd","7389,1462"等.</param>
        /// <param name="delay">每按下一个按键，需要延时多久. 单位毫秒.这个值越大，按的速度越慢。</param>
        /// <returns></returns>
        public void KeyPressString(string str, int delay)
        {
            foreach (char strChar in str)
            {
                KeyPressChar(strChar.ToString());
            }
        }


        public bool LeftDoubleClick() => instance().LeftDoubleClick().Success();
        public bool LeftClick() => instance().LeftClick().Success();
        public bool LeftDown() => instance().LeftDown().Success();
        public bool LeftUp() => instance().LeftUp().Success();
        public bool MiddleClick() => instance().MiddleClick().Success();
        public bool RightClick() => instance().RightClick().Success();
        public bool RightDown() => instance().RightDown().Success();
        public bool RightUp() => instance().RightUp().Success();
        public bool WheelDown() => instance().WheelDown().Success();
        public bool WheelUp() => instance().WheelUp().Success();

        /// <summary>
        /// 设置按键时,键盘按下和弹起的时间间隔。高级用户使用。某些窗口可能需要调整这个参数才可以正常按键。
        /// </summary>
        /// <param name="type"></param>
        /// <param name="delay"></param>
        /// <returns></returns>
        public bool SetKeypadDelay(string type, int delay) => instance().SetKeypadDelay(type, delay).Success();
        /// <summary>
        /// 设置鼠标单击或者双击时,鼠标按下和弹起的时间间隔。高级用户使用。某些窗口可能需要调整这个参数才可以正常点击。
        /// </summary>
        /// <param name="type"></param>
        /// <param name="delay"></param>
        /// <returns></returns>
        public bool SetMouseDelay(string type, int delay) => instance().SetMouseDelay(type, delay).Success();

        /// <summary>
        /// 鼠标相对于上次的位置移动rx,ry
        /// </summary>
        /// <param name="offsetX"></param>
        /// <param name="offsetY"></param>
        /// <returns></returns>
        public bool MoveR(int offsetX, int offsetY) => instance().MoveR(offsetX, offsetY).Success();
        public bool MoveTo(Point point) => instance().MoveTo(point.X, point.Y).Success();
        /// <summary>
        /// 注: 此函数的意思是移动鼠标到指定的范围(x,y,x+w,y+h)内的任意随机一点.
        /// </summary>
        /// <param name="point"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public Point MoveTo(Point point, Size size) => instance().MoveToEx(point.X, point.Y, size.Width, size.Height).ToPoint();

        /// <summary>
        /// 等待指定的按键按下 (前台,不是后台)
        /// </summary>
        /// <param name="keyCode">虚拟按键码</param>
        /// <param name="timeout">等待多久,单位毫秒. 如果是0，表示一直等待</param>
        /// <returns></returns>
        public bool IsWaitKeyTimeout(int keyCode, int timeout) => instance().WaitKey(keyCode, timeout) == 0;
    }

    class Others : DmClassModule
    {
        public Others(DM dm) : base(dm) { }

        public bool FindInputMethod(string inputMethod) => instance().FindInputMethod(inputMethod).Success();
    }

    class System : DmClassModule
    {
        public System(DM dm) : base(dm) { }

        public bool Beep(int frequency, int duration) => instance().Beep(frequency, duration).Success();

        /// <summary>
        /// [收费]
        /// 检测当前系统是否有开启屏幕字体平滑.
        /// 注: 只有WIN7 VISTA WIN2008以及以上系统才有UAC设置
        /// </summary>
        /// <returns></returns>
        public bool CheckFontSmooth() => instance().CheckFontSmooth().Success();
        public bool DisableFontSmooth() => instance().DisableFontSmooth().Success();
        public bool DisablePowerSave() => instance().DisablePowerSave().Success();
        public bool DisableScreenSave() => instance().DisableScreenSave().Success();

        public string GetClipboard() => instance().GetClipboard();
        public bool SetClipboard(string data) => instance().SetClipboard(data).Success();

        /// <summary>
        /// 得到系统的路径 
        /// </summary>
        /// <param name="type">
        /// 取值为以下类型
        /// 0 : 获取当前路径
        /// 1 : 获取系统路径(system32路径)
        /// 2 : 获取windows路径(windows所在路径)
        /// 3 : 获取临时目录路径(temp)
        /// 4 : 获取当前进程(exe)所在的路径
        /// </param>
        /// <returns></returns>
        public string GetDir(int type) => instance().GetDir(type);

        /// <summary>
        /// 获取本机的硬盘序列号.支持ide scsi硬盘. 要求调用进程必须有管理员权限. 否则返回空串.
        /// </summary>
        /// <returns></returns>
        public string GetDiskSerial() => instance().GetDiskSerial();

        /// <summary>
        /// 获取本机的机器码.(带网卡). 此机器码用于插件网站后台. 
        /// 要求调用进程必须有管理员权限. 否则返回空串.
        /// </summary>
        /// <returns></returns>
        public string GetMachineCode() => instance().GetMachineCode();
        /// <summary>
        /// 获取本机的机器码.(不带网卡) 要求调用进程必须有管理员权限. 否则返回空串.
        /// </summary>
        /// <returns></returns>
        public string GetMachineCodeNoMac() => instance().GetMachineCodeNoMac();

        public string GetNetTime() => instance().GetNetTime();

        /// <summary>
        /// [收费]
        /// 从网络获取当前北京时间. 同GetNetTime. 但此接口数据是加密传送,以免被人破解. 
        /// </summary>
        /// <returns></returns>
        public string GetNetTimeSafe() => instance().GetNetTimeSafe();

        /// <summary>
        /// 得到操作系统的类型
        /// </summary>
        /// <returns>
        /// 0 : win95/98/me/nt4.0
        /// 1 : xp/2000
        /// 2 : 2003
        /// 3 : win7/vista/2008
        /// </returns>
        public int GetOsType() => instance().GetOsType();

        public int GetScreenDepth() => instance().GetScreenDepth();
        public Size GetScreenSize()
        {
            return new Size
            {
                Width = Screen.PrimaryScreen.Bounds.Width,
                Height = Screen.PrimaryScreen.Bounds.Height,
            };
        }

        /// <summary>
        /// 获取当前系统从开机到现在所经历过的时间，单位是毫秒
        /// </summary>
        /// <returns></returns>
        public int GetTime() => instance().GetTime();

        public bool Is64Bit() => instance().Is64Bit().Success();

        public int Play(string mediaFile) => instance().Play(mediaFile);
        public bool Stop(int playID) => instance().Stop(playID).Success();

        /// <summary>
        /// [收费]
        /// 运行指定的应用程序.
        /// </summary>
        /// <param name="playID"></param>
        /// <param name="mode">
        /// 0 : 普通模式
        /// 1 : 加强模式
        /// </param>
        /// <returns></returns>
        public bool RunAPP(string appPath, int mode) => instance().RunApp(appPath, mode).Success();

        /// <summary>
        /// [收费]
        /// 设置当前系统的硬件加速级别.
        /// </summary>
        /// <param name="level">
        /// 0-5  0表示关闭硬件加速。5表示完全打开硬件加速.
        /// </param>
        /// <returns></returns>
        public bool SetDisplayAcceler(int level) => instance().SetDisplayAcceler(level).Success();

        /// <summary>
        /// 设置系统的分辨率 系统色深 
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="depth"></param>
        /// <returns></returns>
        public bool SetScreen(int width, int height, int depth) => instance().SetScreen(width, height, depth).Success();

        public bool UACEnable() => instance().SetUAC(1).Success();
        public bool UACDisable() => instance().SetUAC(0).Success();

        public bool Logout() => instance().ExitOs(0).Success();
        public bool Shutdown() => instance().ExitOs(1).Success();
        public bool Reboot() => instance().ExitOs(2).Success();

        public bool CheckUAC() => instance().CheckUAC().Success();

        //public bool Delay(int milliseconds) => instance().Delay(milliseconds).Success();

        public Rect ScreenRect() => new Rect(0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);

    }

    class Dict : DmClassModule
    {
        public Dict(DM dm) : base(dm) { }

        /// <summary>
        /// 设置字库文件
        /// </summary>
        /// <param name="index"></param>
        /// <param name="dictFilePath"></param>
        /// <returns></returns>
        public bool SetDict(int index, string dictFilePath) => instance().SetDict(index, dictFilePath).Success();
        public bool UseDict(int index) => instance().UseDict(index).Success();
        public bool AddDict(int index, string dictInfo) => instance().AddDict(index, dictInfo).Success();
        public bool Clear(int index = 0) => instance().ClearDict(index).Success();

        /// <summary>
        /// [收费]
        /// 获取指定字库中指定条目的字库信息.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="fontIndex"></param>
        /// <returns></returns>
        public string GetDict(int index, int fontIndex) => instance().GetDict(index, fontIndex);

        /// <summary>
        /// 获取指定的字库中的字符数量.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public int GetDictCount(int index) => instance().GetDictCount(index);

        /// <summary>
        /// 根据指定的文字，以及指定的系统字库信息，获取字库描述信息.
        /// </summary>
        /// <param name="str">需要获取的字符串</param>
        /// <param name="fontName">系统字体名,比如"宋体"</param>
        /// <param name="fontSize">系统字体尺寸，这个尺寸一定要以大漠综合工具获取的为准.如何获取尺寸看视频教程.</param>
        /// <param name="flag">
        /// 字体类别 取值可以是以下值的组合,比如1+2+4+8,2+4. 0表示正常字体.
        /// 1 : 粗体
        /// 2 : 斜体
        /// 4 : 下划线
        /// 8 : 删除线
        /// </param>
        /// <returns></returns>
        public string GetDictInfo(string str, string fontName, int fontSize, int flag) => instance().GetDictInfo(str, fontName, fontSize, flag);

        /// <summary>
        /// 获取当前使用的字库序号(0-9)
        /// </summary>
        /// <returns></returns>
        public int GetNowDict() => instance().GetNowDict();

        public bool SaveDict(int index, string saveTo) => instance().SaveDict(index, saveTo).Success();

        public bool SetDictPwd(string password) => instance().SetDictPwd(password).Success();

    }

    class Text : DmClassModule
    {
        public Text(DM dm) : base(dm) { }

        /// <summary>
        /// 根据指定的范围,以及指定的颜色描述，提取点阵信息，类似于大漠工具里的单独提取.
        /// </summary>
        /// <param name="word"></param>
        /// <param name="rect"></param>
        /// <param name="colorList"></param>
        /// <returns></returns>
        public string FetchWord(string word, Rect rect, ColorList colorList)
        {
            return instance().FetchWord(rect.Left, rect.Top, rect.Right, rect.Bottom, colorList.ToString(), word);
        }

        public FindTextResult FindStr(ItemList wordList, Rect rect, ColorList colorList, double sim = 1.0)
        {
            object x, y;
            int ret = instance().FindStr(
                rect.Left,
                rect.Top,
                rect.Right,
                rect.Bottom,
                wordList.ToString(),
                colorList.ToString(),
                sim,
                out x, out y
                );
            if (ret == -1) { return new FindTextResult(); }

            return new FindTextResult(ret, wordList[ret], x, y);
        }

        public FindTextResult FindStr(string word, Rect rect, string color, double sim = 1.0)
        {
            return FindStr(
                new ItemList { word },
                rect,
                new ColorList { new Color(color) },
                sim
                );
        }

        public FindTextResult FindStr(ItemList wordList, Rect rect, ColorList colorList, FindFont font, double sim = 1.0)
        {
            object x, y;
            int ret = instance().FindStrWithFont(
                rect.Left, rect.Top, rect.Right, rect.Bottom,
                wordList.ToString(),
                colorList.ToString(),
                sim,
                font.Name, font.Size, font.Flag,
                out x, out y
                );
            if (ret == -1) { return new FindTextResult(); }

            return new FindTextResult(ret, wordList[ret], x, y);
        }

        public FindTextResult FindStr(string word, Rect rect, string color, FindFont font, double sim = 1.0)
        {
            return FindStr(
                new ItemList { word },
                rect,
                new ColorList { new Color(color) },
                font,
                sim
                );
        }

        public FindTextResult FindStrFast(ItemList wordList, Rect rect, ColorList colorList, double sim = 1.0)
        {
            object x, y;
            int ret = instance().FindStrFast(
                rect.Left,
                rect.Top,
                rect.Right,
                rect.Bottom,
                wordList.ToString(),
                colorList.ToString(),
                sim,
                out x, out y
                );
            if (ret == -1) { return new FindTextResult(); }

            return new FindTextResult(ret, wordList[ret], x, y);
        }

        public FindTextResult FindStrFast(string word, Rect rect, string color, double sim = 1.0)
        {
            return FindStrFast(
                new ItemList { word },
                rect,
                new ColorList { new Color(color) },
                sim
                );
        }

        public List<FindTextResult> FindStrEx(ItemList wordList, Rect rect, ColorList colorList, double sim = 1.0)
        {
            string retData = instance().FindStrEx(
                rect.Left,
                rect.Top,
                rect.Right,
                rect.Bottom,
                wordList.ToString(),
                colorList.ToString(),
                sim
                );

            List<string> listItems = new List<string>();
            listItems.AddRange(retData.Split('|'));

            List<FindTextResult> resultList = new List<FindTextResult>();
            foreach (string item in listItems)
            {
                resultList.Add(new FindTextResult(item, wordList));
            }

            return resultList;
        }

        public FindTextResult FindStrEx(string word, Rect rect, string color, double sim = 1.0)
        {
            var findResult = FindStrEx(new ItemList { word }, rect, new ColorList { new Color(color) }, sim);
            if (findResult.Count > 0) return findResult[0];

            return new FindTextResult();
        }

        public List<FindTextResult> FindStrEx(ItemList wordList, Rect rect, ColorList colorList, FindFont font, double sim = 1.0)
        {
            string retData = instance().FindStrWithFontEx(
                rect.Left, rect.Top, rect.Right, rect.Bottom,
                wordList.ToString(),
                colorList.ToString(),
                sim,
                font.Name, font.Size, font.Flag
                );
            List<string> listItems = new List<string>();
            listItems.AddRange(retData.Split('|'));

            List<FindTextResult> resultList = new List<FindTextResult>();
            foreach (string item in listItems)
            {
                resultList.Add(new FindTextResult(item, wordList));
            }

            return resultList;
        }

        public FindTextResult FindStrEx(string word, Rect rect, string color, FindFont font, double sim = 1.0)
        {
            var findResult = FindStrEx(new ItemList { word }, rect, new ColorList { new Color(color) }, font, sim);
            if (findResult.Count > 0) return findResult[0];

            return new FindTextResult();
        }

        public List<FindTextResult> FindStrFastEx(ItemList wordList, Rect rect, ColorList colorList, double sim = 1.0)
        {
            string retData = instance().FindStrFastEx(
                rect.Left,
                rect.Top,
                rect.Right,
                rect.Bottom,
                wordList.ToString(),
                colorList.ToString(),
                sim
                );

            List<string> listItems = new List<string>();
            listItems.AddRange(retData.Split('|'));

            List<FindTextResult> resultList = new List<FindTextResult>();
            foreach (string item in listItems)
            {
                resultList.Add(new FindTextResult(item, wordList));
            }

            return resultList;
        }

        public FindTextResult FindStrFastEx(string word, Rect rect, string color, double sim = 1.0)
        {
            var findResult = FindStrFastEx(new ItemList { word }, rect, new ColorList { new Color(color) }, sim);
            if (findResult.Count > 0) return findResult[0];

            return new FindTextResult();
        }

        public string Ocr(Rect rect, ColorList colorList, double sim = 1.0)
        {
            return instance().Ocr(rect.Left, rect.Top, rect.Right, rect.Bottom, colorList.ToString(), sim);
        }

        public string Ocr(string filePath, Rect rect, ColorList colorList, double sim = 1.0)
        {
            return instance().OcrInFile(rect.Left, rect.Top, rect.Right, rect.Bottom, filePath, colorList.ToString(), sim);
        }

        public string OcrEx(Rect rect, ColorList colorList, double sim = 1.0)
        {
            return instance().OcrEx(rect.Left, rect.Top, rect.Right, rect.Bottom, colorList.ToString(), sim);
        }

        public bool EnableExtraOcr() => instance().SetExactOcr(1).Success();
        public bool DisableExtraOcr() => instance().SetExactOcr(0).Success();

        public bool SetMinColGap(int gap) => instance().SetMinColGap(gap).Success();
        public bool SetMinRowGap(int gap) => instance().SetMinRowGap(gap).Success();
        public bool SetRowGapNoDict(int gap) => instance().SetRowGapNoDict(gap).Success();
        public bool SetWordGap(int gap) => instance().SetWordGap(gap).Success();
        public bool SetWordGapNoDict(int gap) => instance().SetWordGapNoDict(gap).Success();
        public bool SetWordLineHeight(int lineHeight) => instance().SetWordLineHeight(lineHeight).Success();
        public bool SetWordLineHeightNoDict(int lineHeight) => instance().SetWordLineHeightNoDict(lineHeight).Success();
    }

    class ColorPic : DmClassModule
    {
        public ColorPic(DM dm) : base(dm) { }

        public string AppendPicAddr(string picInfo, int addr, int size) => instance().AppendPicAddr(picInfo, addr, size);

        public string BGR2RGB(string color) => instance().BGR2RGB(color);

        public bool Capture(Rect rect, string saveTo) => instance().Capture(rect.Left, rect.Top, rect.Right, rect.Top, saveTo).Success();
        public bool CaptureGIF(Rect rect, string saveTo, int delay, int duration) => instance().CaptureGif(rect.Left, rect.Top, rect.Right, rect.Top, saveTo, delay, duration).Success();
        public bool CaptureJPG(Rect rect, string saveTo, int quality = 100) => instance().CaptureJpg(rect.Left, rect.Top, rect.Right, rect.Top, saveTo, quality).Success();
        public bool CapturePNG(Rect rect, string saveTo) => instance().CapturePng(rect.Left, rect.Top, rect.Right, rect.Top, saveTo).Success();
        public bool CapturePre(string saveTo) => instance().CapturePre(saveTo).Success();

        public bool IsColorSimilar(Point pt, string color, double sim = 1.0) => instance().CmpColor(pt.X, pt.Y, color, sim) == 0;

        public bool EnableDebug() => instance().EnableDisplayDebug(1).Success();
        public bool DisableDebug() => instance().EnableDisplayDebug(0).Success();


        public bool EnableGetColorByCapture() => instance().EnableGetColorByCapture(1).Success();
        public bool DisableGetColorByCapture() => instance().EnableGetColorByCapture(0).Success();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="colorList"></param>
        /// <param name="sim"></param>
        /// <param name="direction">
        /// 查找方向 0: 从左到右,从上到下 
        /// 1: 从左到右,从下到上 
        /// 2: 从右到左,从上到下 
        /// 3: 从右到左,从下到上 
        /// 4：从中心往外查找
        /// 5: 从上到下,从左到右 
        /// 6: 从上到下,从右到左
        /// 7: 从下到上,从左到右
        /// 8: 从下到上,从右到左
        /// </param>
        /// <returns></returns>
        public Point FindColor(Rect rect, ColorList colorList, double sim = 1.0, int direction = 1)
        {
            object x, y;
            if (instance().FindColor(rect.Left, rect.Top, rect.Right, rect.Bottom, colorList.ToString(), sim, direction, out x, out y).Success())
            {
                return new Point(Convert.ToInt32(x), Convert.ToInt32(y));
            }
            return new Point();
        }

        public Point FindColor(Rect rect, string color, double sim = 1.0, int direction = 1)
        {
            return FindColor(rect, new ColorList { new Color(color) }, sim, direction);
        }
        /// <summary>
        /// [收费]
        /// 查找指定区域内的所有颜色
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="colorList"></param>
        /// <param name="sim"></param>
        /// <returns></returns>
        public bool FindMulColor(Rect rect, ColorList colorList, double sim = 1.0) => instance().FindMulColor(rect.Left, rect.Top, rect.Right, rect.Bottom, colorList.ToString(), sim).Success();
        public bool FindMulColor(Rect rect, string color, double sim = 1.0) => FindMulColor(rect, new ColorList { new Color(color) }, sim);

        public Point FindMultiColor(Rect rect, string firstColor, string offsetColor, double sim = 1.0, int direction = 0)
        {
            object x, y;
            if (instance().FindMultiColor(rect.Left, rect.Top, rect.Right, rect.Bottom, firstColor, offsetColor, sim, direction, out x, out y).Success())
            {
                return new Point
                {
                    X = Convert.ToInt32(x),
                    Y = Convert.ToInt32(y),
                };
            }
            return new Point();
        }

        public FindPictureResult FindPic(Rect rect, ItemList pictureList, string deltaColor, double sim = 1.0, int direction = 0)
        {
            object x, y;
            int result = instance().FindPic(rect.Left, rect.Top, rect.Right, rect.Bottom, pictureList.ToString(), deltaColor, sim, direction, out x, out y);

            if (result == -1)
            {
                return new FindPictureResult();
            }
            return new FindPictureResult(result, pictureList[result], x, y);
        }

        public FindPictureResult FindPic(Rect rect, string picture, string deltaColor, double sim = 1.0, int direction = 0) => FindPic(rect, new ItemList { picture }, deltaColor, sim, direction);

        public List<FindPictureResult> FindPicEx(Rect rect, ItemList pictureList, string deltaColor, double sim = 1.0, int direction = 0)
        {
            object x, y;
            string retData = instance().FindPicEx(rect.Left, rect.Top, rect.Right, rect.Bottom, pictureList.ToString(), deltaColor, sim, direction);

            List<string> listItems = new List<string>();
            listItems.AddRange(retData.Split('|'));

            List<FindPictureResult> resultList = new List<FindPictureResult>();
            foreach (string item in listItems)
            {
                resultList.Add(new FindPictureResult(item, pictureList));
            }

            return resultList;
        }

        public List<FindPictureResult> FindPicEx(Rect rect, string picture, string deltaColor, double sim = 1.0, int direction = 0) => FindPicEx(rect, new ItemList { picture }, deltaColor, sim, direction);

        public bool LoadPic(ItemList picList) => instance().LoadPic(picList.ToString()).Success();
        public bool LoadPic(string picList) => instance().LoadPic(picList).Success();

        public bool FreePic(ItemList picList) => instance().FreePic(picList.ToString()).Success();
        public bool FreePic(string picList) => instance().FreePic(picList).Success();

        public string GetColor(Point pt) => instance().GetColor(pt.X, pt.Y);

        public int GetColorNum(Rect rect, string color, double sim = 1.0) => instance().GetColorNum(rect.Left, rect.Top, rect.Right, rect.Bottom, color, sim);
        public int GetColorNum(Rect rect, ItemList colorList, double sim = 1.0) => instance().GetColorNum(rect.Left, rect.Top, rect.Right, rect.Bottom, colorList.ToString(), sim);

        public Size GetPicSize(string picName)
        {
            string size = instance().GetPicSize(picName);
            return new Size(size, ',');
        }

        public int GetScreenData(Rect rect) => instance().GetScreenData(rect.Left, rect.Top, rect.Right, rect.Bottom);
        /// <summary>
        /// [收费]
        /// 获取指定区域的图像,用24位位图的数据格式返回,（不适合按键使用）方便二次开发.
        /// </summary>
        /// <param name="rect"></param>
        /// <returns></returns>
        public string GetScreenDataBmp(Rect rect)
        {
            object data, size;
            if (instance().GetScreenDataBmp(rect.Left, rect.Top, rect.Right, rect.Bottom, out data, out size).Success())
            {
                return Convert.ToString(data);
            }
            return String.Empty;
        }

        public bool Image2Bmp(string srcPic, string dstPic) => instance().ImageToBmp(srcPic, dstPic).Success();

        public bool IsDisplayDead(Rect rect, int timeout) => instance().IsDisplayDead(rect.Left, rect.Top, rect.Right, rect.Bottom, timeout).Success();

        /// <summary>
        /// 根据通配符获取文件集合. 方便用于FindPic和FindPicEx
        /// </summary>
        /// <param name="picName"></param>
        /// <returns></returns>
        public string MatchPictureName(string picName) => instance().MatchPicName(picName);
    }

    class FindColorResult
    {

    }

    class Color
    {
        public string Main = "000000";
        public string Offset = "000000";
        public Color()
        {
        }

        public Color(string main, string offset)
        {
            Main = main;
            Offset = offset;
        }

        public Color(string colorPair)
        {
            string[] pair = colorPair.Split('-');

            Main = pair[0];
            if (pair.Length == 2)
            {
                Offset = pair[1];
            }
        }
        public override string ToString()
        {
            return $"{Main}-{Offset}";
        }
    }

    class ColorList : List<Color>
    {
        private bool isBackgroundColorMode = false;

        public ColorList BackgroundColorMode()
        {
            isBackgroundColorMode = true;
            return this;
        }

        public override string ToString()
        {
            List<string> strList = new List<string>();
            foreach (Color item in this)
            {
                strList.Add(item.ToString());
            }

            string colorString = String.Join(",", strList.ToArray());
            if (isBackgroundColorMode)
            {
                return "b@" + colorString;
            }
            return colorString;
        }
    }

    class ItemList : List<string>
    {

        public override string ToString()
        {
            return String.Join("|", this.ToArray());
        }
    }

    class FindTextResult
    {
        public Point Pos = new Point(0, 0);
        public string Word = "";
        public int Index = 0;
        private bool success = false;

        public FindTextResult() { }

        public FindTextResult(int index, string word, int x, int y)
        {
            Pos = new Point(x, y);
            Word = word;
            Index = index;
            success = true;
        }

        public FindTextResult(string resultString, List<string> wordList)
        {
            string[] resultList = resultString.Split(',');

            Index = resultString[0];
            Pos = new Point(resultString[1], resultString[2]);
            Word = wordList[Index];
        }

        public FindTextResult(int index, string word, object x, object y)
        {
            Pos = new Point(Convert.ToInt32(x), Convert.ToInt32(y));
            Word = word;
            Index = index;
            success = true;
        }

        public bool Success()
        {
            return success;
        }
    }


    class FindPictureResult
    {
        public Point Pos = new Point(0, 0);
        public string Picture = "";
        public int Index = 0;
        private bool success = false;

        public FindPictureResult() { }

        public FindPictureResult(int index, string picture, int x, int y)
        {
            Pos = new Point(x, y);
            Picture = picture;
            Index = index;
            success = true;
        }

        public FindPictureResult(string resultString, List<string> picList)
        {
            string[] resultList = resultString.Split(',');

            Index = resultString[0];
            Pos = new Point(resultString[1], resultString[2]);
            Picture = picList[Index];
        }

        public FindPictureResult(int index, string picture, object x, object y)
        {
            Pos = new Point(Convert.ToInt32(x), Convert.ToInt32(y));
            Picture = picture;
            Index = index;
            success = true;
        }

        public bool Success()
        {
            return success;
        }
    }

    class FindFont
    {
        public string Name;
        public int Size;
        public int Flag;
    }


    public static class ExtendFunc
    {
        public static bool Success(this int retCode)
        {
            return retCode != 0;
        }

        public static Point ToPoint(this string pointString)
        {
            if (!pointString.Length.Success())
            {
                return new Point();
            }
            string[] retList = pointString.Split(',');
            return new Point
            {
                X = Convert.ToInt32(retList[0]),
                Y = Convert.ToInt32(retList[1]),
            };
        }
    }


    class Tools
    {
        public static List<int> StringToListInt(char splitChar, string rawData)
        {
            string[] listData = rawData.Split(splitChar);

            List<int> listType = new List<int>();
            foreach (string item in listData)
            {
                listType.Add(Convert.ToInt32(item));
            }

            return listType;
        }
    }

    /// <summary>
    /// Target 字符串: 查找串1. (内容取决于flag1的值)
    /// Flag整形数: 取值如下:
    ///     0表示Target的内容是标题
    ///     1表示Target的内容是程序名字. (比如notepad)
    ///     2表示Target的内容是类名
    ///     3表示Target的内容是程序路径.(不包含盘符, 比如\windows\system32)
    ///     4表示Target的内容是父句柄.(十进制表达的串)
    ///     5表示Target的内容是父窗口标题
    ///     6表示Target的内容是父窗口类名
    ///     7表示Target的内容是顶级窗口句柄.(十进制表达的串)
    ///     8表示Target的内容是顶级窗口标题
    ///     9表示Target的内容是顶级窗口类名
    /// Type 整形数: 取值如下
    ///     0: 精确判断
    ///     1: 模糊判断
    /// </summary>
    struct FindWindowSuperCondition
    {
        public string Target;
        public int Flag;
        public int Type;
    }

    class Size
    {
        public int Width = 0;
        public int Height = 0;

        public Size() { }
        public Size(int width, int height)
        {
            Width = width;
            Height = height;
        }

        public Size(string sizeList, params char[] splitChar)
        {
            string[] list = sizeList.Split(splitChar);
            Width = Convert.ToInt32(list[0]);
            Height = Convert.ToInt32(list[1]);
        }

        public bool Equal(Size size)
        {
            if (size.Width == Width && size.Height == Height)
            {
                return true;
            }
            return false;
        }

        public bool Success()
        {
            if (Width == 0 && Height == 0)
            {
                return false;
            }
            return true;
        }
    }
    class Rect
    {
        public int Left = 0;
        public int Top = 0;
        public int Right = 0;
        public int Bottom = 0;

        public Rect() { }

        public Rect(int left, int top, int right, int bottom)
        {
            Left = left;
            Top = top;
            Right = right;
            Bottom = bottom;
        }

        public bool Equal(Rect rect)
        {
            if (Left == rect.Left && Top == rect.Top && Right == rect.Right && Bottom == rect.Bottom)
            {
                return true;
            }
            return false;
        }

        public bool IsFail()
        {
            if (Left == 0 && Top == 0 && Right == 0 && Bottom == 0)
            {
                return true;
            }
            return false;
        }

        public int Width()
        {
            return this.Right - this.Left;
        }

        public int Height()
        {
            return this.Bottom - this.Top;
        }
    }

    public class Point
    {
        public int X = 0;
        public int Y = 0;
        public Point(int x = 0, int y = 0)
        {
            this.X = x;
            this.Y = y;
        }

        public bool Equal(Point point)
        {
            if (this.X == point.X && this.Y == point.Y)
            {
                return true;
            }
            return false;
        }
    }

}